home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 182_01 / unixusq.c < prev    next >
Text File  |  1990-07-30  |  7KB  |  300 lines

  1. static char *sccsid = "@(#)usq.c        1.7u (UCF) 82/12/15";
  2. /*
  3.  *     usq.c - CP/M compatible file unsqueezer utility
  4.  *
  5.  *    compile as follows:
  6.  *    cc [-DVAX] -O usq.c -o usq
  7.  *       (define VAX only if running on VAX)
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <signal.h>
  12. #include <ctype.h>
  13.  
  14. #define TRUE 1
  15. #define FALSE 0
  16. #define ERROR (-1)
  17. #define PATHLEN    312    /* Number of characters allowed in pathname */
  18. #define OK 0
  19.  
  20. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  21. #define DLE 0x90        /* repeat byte flag */
  22. #define SPEOF 256        /* special endfile token */
  23. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  24. #define LARGE 30000
  25.  
  26. #ifdef VAX   /* then we don't want 32 bit integers */
  27.  
  28. typedef short INT;
  29. typedef unsigned short UNSIGNED;
  30.  
  31. #else   /*  16 bit machines  */
  32.  
  33. typedef int INT;
  34. typedef unsigned UNSIGNED;
  35.  
  36. #endif
  37.  
  38. struct _sqleaf {        /* Decoding tree */
  39.     INT _children[2];    /* left, right */
  40. };
  41. struct _sqleaf Dnode[NUMVALS - 1];
  42.  
  43.  
  44. INT Bpos;        /* last bit position read */
  45. INT Curin;        /* last byte value read */
  46. INT Repct;        /* Number of times to return value */
  47. INT Value;        /* current byte value or EOF */
  48.  
  49. INT MakeLCPathname=TRUE;    /* translate pathname to lc if all caps */
  50. INT Nlmode=FALSE;        /* zap cr's if true */
  51. INT Inbackground = FALSE;
  52.  
  53. INT getcr(), getuhuff(), portgetw();
  54.  
  55. main(argc, argv)
  56. char *argv[];
  57. {
  58.     register char *cp;
  59.     register INT npats=0;
  60.     char **patts;
  61.     INT n, errorstat;
  62.  
  63.     if (signal(SIGINT, SIG_IGN)==SIG_IGN)
  64.         Inbackground++;
  65.     else
  66.         signal(SIGINT, SIG_DFL);
  67.     signal(SIGHUP, SIG_IGN);
  68.     errorstat=0;
  69.     if(argc<2)
  70.         goto usage;
  71.     while (--argc) {
  72.         cp = *++argv;
  73.         if(*cp == '-') {
  74.             while( *++cp) {
  75.                 switch(*cp) {
  76.                 case 'n':
  77.                     Nlmode=TRUE; break;
  78.                 case 'u':
  79.                     MakeLCPathname=FALSE; break;
  80.                 default:
  81.                     goto usage;
  82.                 }
  83.             }
  84.         }
  85.         else if( !npats && argc>0) {
  86.             if(argv[0][0]) {
  87.                 npats=argc;
  88.                 patts=argv;
  89.             }
  90.         }
  91.     }
  92.     if(npats < 1) {
  93. usage:
  94.         fprintf(stderr,"Usage: usq [-nu] file ...\n");
  95.         fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
  96.         fprintf(stderr,"\t-u preserve Uppercase pathnames\n");
  97.         exit(1);
  98.     }
  99.     for(n=0; n<npats; ++n)
  100.         errorstat |= squeeze(patts[n]);
  101.     exit(errorstat != 0);
  102. }
  103.  
  104. /*
  105.     The following code is primarily from typesq.c and utr.c.  Typesq
  106. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  107. to typesq) were made by Bob Mathias, I am responsible for the butchery
  108. done to make it work with cat.
  109.  
  110. */
  111.  
  112. FILE *in, *out;
  113. squeeze(fname)
  114. char *fname;
  115. {
  116.     register INT i, c;
  117.     register char *p;
  118.     register INT numnodes;            /* size of decoding tree */
  119.     register UNSIGNED crc;
  120.     UNSIGNED filecrc;
  121.     char origname[PATHLEN];        /* Original file name without drive */
  122.  
  123.     init_cr(); init_huff(); crc=0;
  124.  
  125.     if((in=fopen( fname, "r"))==NULL) {
  126.         fprintf(stderr, "usq: can't open %s\n", fname);
  127.         return ERROR;
  128.     }
  129.     if(portgetw(in) != (INT) RECOGNIZE) {/* Process header */
  130.         fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
  131.         return(ERROR);
  132.     }
  133.     filecrc = (UNSIGNED) portgetw(in);    /* checksum */
  134.     p = origname;                /* Get original file name */
  135.     do {                    /* send it to array */
  136.         *p = getc(in);
  137.     } while(*p++ != '\0');
  138.  
  139.     numnodes = portgetw(in);
  140.     if(numnodes < 0 || numnodes >= NUMVALS) {
  141.         fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
  142.         fclose(in);
  143.         return(ERROR);
  144.     }
  145.     /* Initialize for possible empty tree (SPEOF only) */
  146.     Dnode[0]._children[0] = -(SPEOF + 1);
  147.     Dnode[0]._children[1] = -(SPEOF + 1);
  148.  
  149.     for(i = 0; i < numnodes; ++i) {    /* Get decoding tree from file */
  150.         Dnode[i]._children[0] = portgetw(in);
  151.         Dnode[i]._children[1] = portgetw(in);
  152.     }
  153.     /* Get translated output bytes and write file */
  154.     if(MakeLCPathname && !IsAnyLower(origname))
  155.         uncaps(origname);
  156.     for(p=origname; *p; ++p)        /* change / to _ */
  157.         if( *p == '/')
  158.             *p = '_';
  159.     if (!Inbackground)
  160.         fprintf(stderr, "usq: %s -> %s\n",fname,origname);
  161.     if((out=fopen(origname, "w"))==NULL) {
  162.         fprintf(stderr, "usq: can't create %s\n", origname);
  163.     }
  164.     while ((c = getcr()) != EOF) {
  165.         crc += (UNSIGNED) c;
  166.         if ( c == '\r' && Nlmode)
  167.             continue;
  168.         putc(c, out);
  169.     }
  170.     fclose(in);
  171.     fflush(out);
  172.     fclose(out);
  173.     if( crc != filecrc ) {
  174.         fprintf(stderr, "usq: bad checksum in %s\n", fname);
  175.         fflush(stdout);
  176.         return(ERROR);
  177.     }
  178.     return(OK);
  179. }
  180. /*** from utr.c - */
  181. /* initialize decoding functions */
  182.  
  183. init_cr()
  184. {
  185.     Repct = 0;
  186. }
  187.  
  188. init_huff()
  189. {
  190.     Bpos = 99;    /* force initial read */
  191. }
  192.  
  193. /* Get bytes with decoding - this decodes repetition,
  194.  * calls getuhuff to decode file stream into byte
  195.  * level code with only repetition encoding.
  196.  *
  197.  * The code is simple passing through of bytes except
  198.  * that DLE is encoded as DLE-zero and other values
  199.  * repeated more than twice are encoded as value-DLE-count.
  200.  */
  201.  
  202. INT
  203. getcr()
  204. {
  205.     register INT c;
  206.  
  207.     if(Repct > 0) {
  208.         /* Expanding a repeated char */
  209.         --Repct;
  210.         return(Value);
  211.     } else {
  212.         /* Nothing unusual */
  213.         if((c = getuhuff()) != DLE) {
  214.             /* It's not the special delimiter */
  215.             Value = c;
  216.             if(Value == EOF)
  217.                 Repct = LARGE;
  218.             return(Value);
  219.         } else {
  220.             /* Special token */
  221.             if((Repct = getuhuff()) == 0)
  222.                 /* DLE, zero represents DLE */
  223.                 return(DLE);
  224.             else {
  225.                 /* Begin expanding repetition */
  226.                 Repct -= 2;    /* 2nd time */
  227.                 return(Value);
  228.             }
  229.         }
  230.     }
  231. }
  232. /* Decode file stream into a byte level code with only
  233.  * repetition encoding remaining.
  234.  */
  235.  
  236. INT
  237. getuhuff()
  238. {
  239.     register INT i;
  240.  
  241.     /* Follow bit stream in tree to a leaf*/
  242.     i = 0;    /* Start at root of tree */
  243.     do {
  244.         if(++Bpos > 7) {
  245.             if((Curin = getc(in)) == ERROR)
  246.                 return(ERROR);
  247.             Bpos = 0;
  248.             /* move a level deeper in tree */
  249.             i = Dnode[i]._children[1 & Curin];
  250.         } else
  251.             i = Dnode[i]._children[1 & (Curin >>= 1)];
  252.     } while(i >= 0);
  253.  
  254.     /* Decode fake node index to original data value */
  255.     i = -(i + 1);
  256.     /* Decode special endfile token to normal EOF */
  257.     i = (i == SPEOF) ? EOF : i;
  258.     return(i);
  259. }
  260. /*
  261.  * Machine independent getw which always gets bytes in the same order
  262.  *  as the CP/M version of SQ wrote them
  263.  */
  264. INT
  265. portgetw(f)
  266. FILE *f;
  267. {
  268.     register INT c;
  269.  
  270.     c = getc(f) & 0377;
  271.     return(c | (getc(f) << 8));
  272. }
  273.  
  274.  
  275. /* make string s lower case */
  276. uncaps(s)
  277. char *s;
  278. {
  279.     for( ; *s; ++s)
  280.         if(isupper(*s))
  281.             *s = tolower(*s);
  282. }
  283.  
  284.  
  285. /*
  286.  * IsAnyLower returns TRUE if string s has lower case letters.
  287.  */
  288. IsAnyLower(s)
  289. char *s;
  290. {
  291.     for( ; *s; ++s)
  292.         if (islower(*s))
  293.             return(TRUE);
  294.     return(FALSE);
  295. }
  296.  
  297.  
  298.  
  299.  
  300.